//
// Created by 32827 on 2023/12/6.
//

#ifndef YZFRAME_YZ_SPI_SD_H
#define YZFRAME_YZ_SPI_SD_H
#include "yz.h"
#include "yzl_softport_spi.h"
#define MicroSD_CS_SET yzf_gpio_set_1(GPIOC,YZF_PIN_4)
#define MicroSD_CS_RESET yzf_gpio_set_0(GPIOC,YZF_PIN_4)

#define MicroSD_READ_TOKEN 0b11111110
#define MicroSD_SINGLE_WRITE_TOKEN 0b11111110

#define MicroSD_MULTIPLE_WRITE_TOKEN_START 0b11111100
#define MicroSD_MULTIPLE_WRITE_TOKEN_END 0b11111101

#define YZL_SD_SPI_Enable_Check(SPI) if(!yzf_spi_is_enabled(SPI)){YZL_SD_SPI_ReadWriteByteStart(SPI)}
#define YZL_SD_SPI_Use_Softport OFF
extern YZF_SPI_POINTER MicroSD_SPI;
extern uint8_t YZL_SD_SPI_WriteResponse;

enum SD_Response{
    SD_Response_0,
    SD_Response_1,
    SD_Response_2,
    SD_Response_3,
    SD_Response_6,
    SD_Response_7,
    SD_Response_NONE,
    SD_ERROR
};
#ifdef __cplusplus
extern "C" {
#endif

char yzl_sd_spi_init(YZF_SPI_POINTER spi);    //初始化函数

//have checked
void YZL_SD_SPI_ReadWriteByteStart(YZF_SPI_POINTER spi);

//have checked
char YZL_SD_SPI_ReadWriteByte(YZF_SPI_POINTER spi, char data);

//have checked
void YZL_SD_SPI_ReadWriteByteEnd(YZF_SPI_POINTER spi);

uint8_t *SentCommandToMicroSDV2(YZF_SPI_POINTER spi, char cmd, uint32_t data, uint8_t crc, enum SD_Response res_type);

YZF_RESULT WriteSectorToMicroSD(YZF_SPI_POINTER spi, long addr, YZF_RECV *area);//写一个扇区 512bit
YZF_RESULT WriteSectorsToMicroSD(YZF_SPI_POINTER spi, long addr, YZF_RECV *area, uint16_t len);

YZF_RESULT WriteSectorsToMicroSD_Raw(YZF_SPI_POINTER spi, long addr, uint8_t *area, uint16_t len);

YZF_RESULT ReadSectorFromMicroSD(YZF_SPI_POINTER spi, long sector, YZF_RECV *area);// 读一个扇区
YZF_RESULT ReadSectorsFromMicroSD(YZF_SPI_POINTER spi, long sector, YZF_RECV *area, uint16_t len);// 读一个扇区
YZF_RESULT ReadSectorsFromMicroSD_Raw(YZF_SPI_POINTER spi, long sector, uint8_t *area, uint16_t len);// 读一个扇区

uint8_t *sd_response_block_read(YZF_SPI_POINTER spi, char cmd, uint16_t length, YZF_RECV *area);

uint8_t sd_response_block_read_raw(YZF_SPI_POINTER spi, char cmd, uint16_t length, uint8_t *area);

/**
 * have checked
 * CMD0 go to idle
 * */
YZF_RESULT yz_sd_spi_cmd0(YZF_SPI_POINTER spi);

/**
 * have checked
 * CMD8 Ask if the voltage is in range
 * */
YZF_RESULT yz_sd_spi_cmd8(YZF_SPI_POINTER spi);

YZF_RESULT yz_sd_spi_cmd9(YZF_SPI_POINTER spi);

YZF_RESULT yz_sd_spi_cmd10(YZF_SPI_POINTER spi);

YZF_RESULT yz_sd_spi_cmd12(YZF_SPI_POINTER spi);

YZF_RESULT yz_sd_spi_cmd13(YZF_SPI_POINTER spi);

YZF_RESULT yz_sd_spi_cmd17(YZF_SPI_POINTER spi, uint32_t sector, YZF_RECV *area);

/**
 * have checked
 * CMD18 read multiple blocks
 * */
YZF_RESULT yz_sd_spi_cmd18(YZF_SPI_POINTER spi, uint32_t sector, YZF_RECV *area, uint16_t len);

YZF_RESULT yz_sd_spi_cmd18_raw(YZF_SPI_POINTER spi, uint32_t sector, uint8_t *area, uint16_t len);

YZF_RESULT yz_sd_spi_cmd24(YZF_SPI_POINTER spi, uint32_t sector, YZF_RECV *area);

/**
 * have checked
 * CMD25 write multiple blocks
 * */
YZF_RESULT yz_sd_spi_cmd25(YZF_SPI_POINTER spi, uint32_t sector, YZF_RECV *area, uint16_t count);

/**
 * have checked
 * CMD25 write multiple blocks
 * */
YZF_RESULT yz_sd_spi_cmd25_raw(YZF_SPI_POINTER spi, uint32_t sector, uint8_t *area, uint16_t count);

YZF_RESULT yz_sd_spi_cmd42(YZF_SPI_POINTER spi);

/**
 * have checked
 * CMD55 When you need to send APP_CMD, you need to send CMD55 first
 * */
YZF_RESULT yz_sd_spi_cmd55(YZF_SPI_POINTER spi);

/**
 * have checked
 * CMD58 Get the OCR Register
 * */
YZF_RESULT yz_sd_spi_cmd58(YZF_SPI_POINTER spi);

/**
 * have checked
 * CMD59  off crc test.
 * */
YZF_RESULT yz_sd_spi_cmd59(YZF_SPI_POINTER spi);

/**
 * have checked.
 * ACMD41 Send the host's memory capacity information to the card, and
 * the card will respond with 0x00 if the information is correct.
 * If the information is incorrect, the card will respond with 0x01.
 * 发送主机容量支持信息，并将卡初始化，HCS一般置“1”
 * */
YZF_RESULT yz_sd_spi_acmd41(YZF_SPI_POINTER spi);

//与擦除以提高性能
//YZF_RESULT yz_sd_spi_acmd23(YZF_SPI_POINTER spi);

uint8_t *yz_sd_get_result();

#ifdef __cplusplus
}
#endif
#endif //YZFRAME_YZ_SPI_SD_H
